package club.cearnach.api.property;

import club.cearnach.api.dao.ICityDao;
import club.cearnach.api.dao.IDistrictDao;
import club.cearnach.api.dao.IProvinceDao;
import club.cearnach.api.dao.IStateDao;
import club.cearnach.entity.*;
import club.cearnach.property.PlaceProperty;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.HashMap;
import java.util.List;

/**
 * 海内外各个城市名称与编码
 *
 * @author 阮胜
 * @date 2018/5/13 14:17
 */
@Slf4j
@Component
public class PlaceProperties implements ApplicationListener<ContextRefreshedEvent> {

    private static final String PLACE_PROPERTY_PATH = "classpath:static/properties/place.txt";
    private final IStateDao stateDao;
    private final IProvinceDao provinceDao;
    private final ICityDao cityDao;
    private final IDistrictDao districtDao;

    private int checkCount = 0;

    public PlaceProperties(IStateDao stateDao, IProvinceDao provinceDao, ICityDao cityDao, IDistrictDao districtDao) {
        this.stateDao = stateDao;
        this.provinceDao = provinceDao;
        this.cityDao = cityDao;
        this.districtDao = districtDao;
    }

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        checkData();
    }

    private void checkData() {
        //如果执行了2次检查,数据还是初始化时候,那么就取消初始化
        if (checkCount > 1) {
            log.error("初始化省市数据表失败!");
            return;
        }
        log.info("开始初始化省市数据表.");
        List<State> stateList = stateDao.findAll();
        List<Province> provinceList = provinceDao.findAll();
        List<City> cityList = cityDao.findAll();
        List<District> districtList = districtDao.findAll();
        if (CollectionUtils.isEmpty(stateList)
                || CollectionUtils.isEmpty(provinceList)
                || CollectionUtils.isEmpty(cityList)
                || CollectionUtils.isEmpty(districtList)) {
            try {
                File file = ResourceUtils.getFile(PLACE_PROPERTY_PATH);
                initPlaceData(file);
                checkData();
                //如果初始化成功,那么不会执行下面的checkCount++语句,不过执行结束后,第一次进入的递归会继续执行下面语句
                checkCount++;
            } catch (FileNotFoundException e) {
                log.error("初始化省市数据表失败! Error:{}", e.getMessage());
            }
        }
        //递归检查完,需要对checkCount进行校验,避免多次初始化MAP.
        if (checkCount > 0) {
            return;
        }

        PlaceProperty.stateMap = new HashMap<>(stateList.size());
        PlaceProperty.provinceMap = new HashMap<>(provinceList.size());
        PlaceProperty.cityMap = new HashMap<>(cityList.size());
        PlaceProperty.districtMap = new HashMap<>(districtList.size());
        stateList.forEach(state -> PlaceProperty.stateMap.put(state.getCode(), state));
        provinceList.forEach(province -> PlaceProperty.provinceMap.put(province.getCode(), province));
        cityList.forEach(city -> PlaceProperty.cityMap.put(city.getCode(), city));
        districtList.forEach(district -> PlaceProperty.districtMap.put(district.getCode(), district));
    }


    /**
     * 初始化省市数据表
     */
    private void initPlaceData(File file) {
        try (FileReader fr = new FileReader(file)) {
            StringBuilder sb = new StringBuilder();
            char[] buf = new char[1024];
            int len;
            while ((len = fr.read(buf)) != -1) {
                sb.append(buf, 0, len);
            }
            Place place = new Place();
            State s = new State(86, "中国");
            place.setState(s);
            State state = stateDao.saveAndFlush(s);
            JSONObject jsonObj = JSONObject.parseObject(sb.toString());
            JSONObject provinceJsonObj = jsonObj.getJSONObject("86");
            provinceJsonObj.forEach((key, value) -> {
                Province p = new Province(Integer.valueOf(key), value.toString(), state);
                Province province = provinceDao.saveAndFlush(p);
                JSONObject cityJsonObj = jsonObj.getJSONObject(key);
                if (cityJsonObj != null) {
                    cityJsonObj.forEach((cityKey, cityValue) -> {
                        City city = new City(Integer.valueOf(cityKey), cityValue.toString(), province);
                        cityDao.saveAndFlush(city);
                        JSONObject districtJsonObj = jsonObj.getJSONObject(cityKey);
                        if (districtJsonObj != null) {
                            districtJsonObj.forEach((dKey, dValue) -> {
                                District district = new District(Integer.valueOf(dKey), dValue.toString(), city);
                                districtDao.saveAndFlush(district);
                            });
                        }
                    });
                }
            });
        } catch (Exception e) {
            log.error(e.getMessage());
        }

    }
}
